import os
from math import floor
from telnetlib import Telnet as T
from socket import timeout
from tkFileDialog import asksaveasfile
import tkMessageBox as MB
import getdata as GD
from time import *
import datetime as DT
import pyodbc

prompt = "S>"
max = 20
DB = "Sandbox.accdb"
tables = ('RawValue',)

def figure_out_restart(date, time):
	now = DT.datetime(date.year, date.month, date.day,
					  time.hour, time.minute)
	dt = DT.timedelta(seconds=15*60)
	temp = now + dt
	minute = 15*floor(temp.minute/15.0)
	return DT.datetime(temp.year, temp.month, temp.day, temp.hour, int(minute))

def get_serial_ports(connection):
	connection.write("who\r\n")
	connection.read_until("\r\n", max)
	tmp = connection.read_until("\r\n", max)
	pids = []
	while "#>" not in tmp:
		tmp = connection.read_until("\r\n", max)
		print tmp
		if "serial" in tmp:
			pids.append(tmp[0])
	return pids

def kill_serial_ports(connection, pids):
	for pid in pids:
		connection.write("kill %s\r\n"%pid)
		tmp = connection.read_until("\r\n", max)
		print tmp

def populateDB(DB, tables, data):
	db = pyodbc.connect('DSN=' + DB.strip(".accdb"))
	curs = db.cursor()
	dbtables = curs.tables()
	for table in tables:
		if table in dbtables:
#			print vars(table)
			print dir(table)
		
class kill_timeout(timeout):
	def __init__(self):
	    timeout.__init__(self)

class DBError(Exception):
	def __init__(self):
	    exception.__init__(self)

IPsPORTs = {'1': ("Mukilteo Bottom", "166.140.17.138", 8001),
			'2': ("Manchester Bottom", "165.151.151.19", 8001),
			'3': ("Squaxin Surface", "166.140.038.220", 4002),
			'4': ("Squaxin Bottom", "166.140.038.220", 4001),
			'5': ("Wilapa Center", "166.130.17.242", 8001)}
# Create menu
que = 'Choose a number: ' + os.linesep
for number in sorted(IPsPORTs):
	place, ip, port = IPsPORTs[number]
	que += str(number) + ": " + place + ' ' + ip + ' ' + str(port) + os.linesep 
selection = raw_input(que)
ip, port = IPsPORTs[str(selection)][1:]
print ip, port
try: # First, kill serial ports if more than one
	tn23 = T(ip, 23, max)
	tmp = tn23.expect(["#>", "login:"],  max)[2]
	print tmp
	if "login:" in tmp:
		print "Entered the login branch"
		tn23.write("admin\r\n")
		tmp = tn23.read_until("password:", max)
		print tmp
		tn23.write("strix!12\r\n")
		tmp = tn23.read_until("#>", max)
		print tmp
	ports_killed = False; out_tries = 0
	while (not ports_killed) and (out_tries < max):		
		print
		print "out_tries: ", out_tries
		out_tries += 1		
		# tmp = tn23.read_until("#>", max)
		# print tmp
		pids = get_serial_ports(tn23)
		print "Serial port IDs: ", pids
		npids = len(pids); in_tries = 0
		if npids == 0: print "No serial connections found"
		while (npids > 1) and (in_tries < max/2): 
			print "in_tries: ", in_tries
			in_tries += 1		
			kill_serial_ports(tn23, pids)
			pids = get_serial_ports(tn23)
			npids = len(pids)			
			if npids == 1: npids = 2 # If this is true, we haven't killed them all
		if npids > 1: # if this is true, we must have tried too many times
			raise kill_timeout
		else:
			ports_killed = True
	if out_tries == max:
		raise kill_timeout
	# Just to be sure
	pids = get_serial_ports(tn23)
	if len(pids) > 1:
		raise kill_timeout
except timeout:
	GD.timeout_exception("Sorry, couldn't get in on port 23 to check for/kill serial ports.\n")
except kill_timeout:
	GD.timeout_exception("Sorry, couldn't kill the serial ports.  Giving up.\n")

tn, data, date, time = GD.getdata((ip, port), max)
data = str(data)
if tn is not None:
	try: # issue delayed logging restart
		print "Issuing restart commands"
		restart = figure_out_restart(date, time)
		cmnd = restart.date().strftime("startmmddyy=%m%d%y\r\n")
		tn.write(cmnd)
		tmp = tn.read_until(prompt, max); data += tmp; print tmp
		cmnd = restart.time().strftime("starthhmmss=%H%M%S\r\n")
		tn.write(cmnd)
		tmp = tn.read_until(prompt, max); data += tmp; print tmp
		temp = "startlater\r\n"
		tn.write(temp)
		temp = tn.read_until(prompt, max); data += temp; print temp
		if "start time =" not in temp:
			raise timeout
		if data[0:4] is not 'None':
			try:
				# First, for security, write data to file
				print "Data retrieved, writing to file"
				fo = asksaveasfile()
				fo.write(data)
				fo.flush()
				fo.close()
				print "Data written successfully to:"
				print fo.name
				# Now push data to DB
				success = False; tries = 0
				while (not success) and (tries < max):
					tries += 1
					success = populateDB(DB, tables, data)
				if tries == max:
					raise DBError
			except IOError:
				t, v, b = sys.exc_info()
				MB.showerror("Sorry!", 
					"Couldn't open file to write data.  Giving up.\n" + 
					str(t) + " " + str(v) + "\n" + str(b))
			except DBError:
				t, v, b = sys.exc_info()
				MB.showerror("Sorry!", 
					"Couldn't push data to tables " + str(tables) + " in DB " + DB +
					" in " + str(max) + " tries.  Giving up.\n" + 
					str(t) + " " + str(v) + "\n" + str(b))
#				tn.close()
		else:
			print "Sorry, no data returned, not sure why."
			print "Please contact david.goldsmith@ecy.wa.gov for assistance."
	except timeout:
		GD.timeout_exception("Couldn't confirm restart.  Giving up.\n")
#		tn.close()
	x = tn.close()
	print x
else:
	MB.showerror("Sorry!", 
		"Couldn't open telnet connection to " + ipport[0] + ", port " +
		str(ipport[1]) + ".")
y = tn23.close()
print y
raw_input("Press Enter to close console and quit.") 